﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Threading.Tasks;
using CryptoQrUtilities;
using CryptoQrUtilities.Cryption;
using Touchless.Vision.Camera;
using InputHandlers.KeyboardHandling;

namespace CryptoQrDemo
{
    class MainClass
    {
        // (Try switching between them..)
        private const string c_localRsaKeyContainerName = "CryptoQrDemo";
        private const string c_remoteRsaKeyContainerName = "test1";

        public static void Main(string[] args)
        {
            QrMessage.AddDotNetContainerDecryptionMethod(c_localRsaKeyContainerName);
            MultiKeyQrMessage.AddDotNetContainerMultiKeyDecryptionMethod(c_localRsaKeyContainerName);
            ContainerBasedRsaProvider.CreateRsaPersistentKeyContainer(c_remoteRsaKeyContainerName);

            Console.WriteLine("Write a word to create Crypted QR, or show a QR to the camera.");
            Console.WriteLine("Type 'load <file-name>' to manually load a QR bitmap.");
            Console.WriteLine("Write 'quit' to exit the demo.");

            var qrUtils = new QrUtilitiesWrapper();
            bool identifiedQr = false;
            string qrText = null;

            using (var camera = CameraService.DefaultCamera)
            {
                string passText = string.Empty;

                var encodeTask = Task.Factory.StartNew(
                    () =>
                    {
                        while (true)
                        {
                            passText = Console.ReadLine();
                            if (passText.Equals("quit"))
                            {
                                break;
                            }

                            if (passText.StartsWith("load "))
                            {
                                var fileName = passText.Substring(5);
                                var qrBitmap = new Bitmap(fileName);

                                var qrDecode = qrUtils.GetQrDecoding(qrBitmap);

                                identifiedQr = (qrDecode != null && qrDecode.Text != null);
                                if (identifiedQr)
                                {
                                    qrText = qrDecode.Text;
                                }
                                else
                                {
                                    Console.WriteLine(">> File '{0}' contains no identifiable QR.", fileName);
                                }

                                continue;
                            }

                            if (string.IsNullOrEmpty(passText))
                            {
                                continue;
                            }

                            var message = new MultiKeyQrMessage(passText, new List<IRsaProvider>
                            {
                                new ContainerBasedRsaProvider(c_remoteRsaKeyContainerName)
                            });
                            //var message = new QrMessage(passText);
                            var newQr = message.SerializeIntoQr();
                            var newQrFileName = ((passText.Length > 8)
                                ? passText.Substring(0, 8)
                                : passText) + ".png";

                            newQr.Save(newQrFileName, ImageFormat.Png);
                            Console.WriteLine(">> Saved the new QR in file '{0}'", newQrFileName);
                        }
                    });

                Bitmap snapshot = null;
                var frameSource = new CameraFrameSource(camera);

                frameSource.Camera.CaptureWidth = 340;
                frameSource.Camera.CaptureHeight = 240;
                frameSource.Camera.Fps = 20;
                frameSource.NewFrame +=
                    (source, frame, fps) =>
                    {
                        if (snapshot != null)
                        {
                            snapshot.Dispose();
                        }

                        snapshot = frame.Image;

                        if (!identifiedQr)
                        {
                            var qrDecode = qrUtils.GetQrDecoding(snapshot);

                            identifiedQr = (qrDecode != null && qrDecode.Text != null);
                            if (identifiedQr)
                            {
                                qrText = qrDecode.Text;
                            }
                        }
                    };

                bool continueDecoding = true;
                var decodingTask = new Thread(
                    () =>
                    {
                        frameSource.StartFrameCapture();
                        Console.WriteLine("Started capturing images from the camera.");

                        while (continueDecoding)
                        {
                            if (identifiedQr)
                            {
                                var deserialized = QrMessage.DeserializeEncodedMessage(qrText);
                                var decodedMessage = deserialized.GetMessageClearText();

                                KeyboardSynth.Type(decodedMessage);

                                Thread.Sleep(TimeSpan.FromSeconds(1));
                                identifiedQr = false;
                            }

                            Thread.Sleep(100);
                        }

                        frameSource.StopFrameCapture();
                        Console.WriteLine("Stopped capturing images from the camera.");
                    });

                decodingTask.SetApartmentState(ApartmentState.STA);
                decodingTask.Start();

                encodeTask.Wait();
                continueDecoding = false; // Stop decoding
            }
        }
    }
}
